package org.haifi.game.compiler;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import javax.tools.JavaFileManager.Location;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 动态编译工具类
 * 
 * @author joycube2
 * 
 */
public class JavaCompilerUtil {
	public static Object compiler(String className, String code) {
		// 动态生成class,替换原有类行为
		try {
			JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
			StandardJavaFileManager fm = compiler.getStandardFileManager(null,
					null, null);
			// 指定生成的class所在位置
			Location location = StandardLocation.CLASS_OUTPUT;
			// 生成的临时目录
			File file = new File("tmp");
			if (!file.exists()) {
				file.mkdirs();
			}
			File[] outputs = new File[] { file };
			fm.setLocation(location, Arrays.asList(outputs));

			JavaFileObject fileObject = new JavaSourceFromString(className
					.substring(className.lastIndexOf(".") + 1), code);
			List<JavaFileObject> jfos = Arrays.asList(fileObject);

			// 设置classpath
			Location classPathLocation = StandardLocation.CLASS_PATH;
			URLClassLoader urlClassLoader = (URLClassLoader) Thread
					.currentThread().getContextClassLoader();
			List<File> files = new ArrayList<File>();
			for (URL url : urlClassLoader.getURLs()) {
				files.add(new File(url.getFile()));
			}
			fm.setLocation(classPathLocation, files);

			boolean b = compiler.getTask(null, fm, null, null, null, jfos)
					.call();
			if (b) {
				// 使用url指定classpath
				URL url = file.toURI().toURL();
				List<URL> urlList = new ArrayList<URL>();

				urlList.add(url);
				URL[] urls = new URL[urlList.size()];
				urlList.toArray(urls);
				URLClassLoader classLoader = new URLClassLoader(urls, Thread
						.currentThread().getContextClassLoader());
				Object object = classLoader.loadClass(className).newInstance();
				log.info("genrate object:" + object);
				return object;
			} else {
				log.error("文件翻译失败:\n" + code);
				return null;
			}
		} catch (Exception e) {
			log.error("ERROR", e);
		}
		return null;
	}

	private static final Log log = LogFactory.getLog(JavaCompilerUtil.class);
}
